// ChatFrame.cs
//
//  Copyright (C) 2008 Jacek Trubłajewicz
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//

using System;
using System.Drawing;
using System.Threading;
using Mono.Unix;
using NLog;

namespace wxGadu
{

	/// <summary>
	/// Represents chat window
	/// </summary>
	public class ChatFrame : wx.Frame
	{
		#region IDs
		private enum Id
		{
			splitterWindow
		}
		#endregion
		
		#region controls
		private wx.BoxSizer topSizer;
		#endregion

		#region windows
		private wx.SplitterWindow splitterWindow;
		private TopChatFramePanel topWindow;
		private BottomChatFramePanel bottomWindow;
		private MainFrame mainFrame;
		#endregion
		
		#region data members
		// keeps chat html formatted code
		private string messagesHtmlCode;
		private Chat chatObject;
		#endregion
		private Mutex messagesMutex;
#if LOG
		private Logger logger = LogManager.GetCurrentClassLogger();
#endif
		
		
		public ChatFrame(wx.Window parent, int id, string title, Point pos, Size size, uint style, Chat chat):
			base(parent, id, title, pos, size, style)
		{
			mainFrame = (MainFrame) parent;
			chatObject = chat;
			
			DoControls();
			DoLayout();
			
			messagesMutex = new Mutex();
			
			EVT_UPDATE_UI((int) FakeId.chatFrameRenderMessages, new wx.EventListener(OnRenderMessages));
			EVT_SIZE(new wx.EventListener(OnChatFrameResize));
			EVT_UPDATE_UI((int) FakeId.chatWindowSizeChanged, new wx.EventListener(UpdateChatWindowSize));
			EVT_UPDATE_UI((int) FakeId.chatFrameRequestUserAttention, new wx.EventListener(GetUserAttention));
			EVT_UPDATE_UI((int) FakeId.clearChatWindow, new wx.EventListener(ClearTopWindow));
			EVT_CLOSE(new wx.EventListener(OnChatFrameClose));
			// set default chat window size
			ChatWindowSizeChagned(this);
		}

		private void DoControls()
		{
			splitterWindow = new wx.SplitterWindow(this, (int) Id.splitterWindow, wx.Window.wxDefaultPosition,
				                             								wx.Window.wxDefaultSize, wx.SplitterWindow.wxSP_LIVE_UPDATE);
			topWindow = new TopChatFramePanel(splitterWindow);
			bottomWindow = new BottomChatFramePanel(splitterWindow);

			// only top window should grow when resized
			splitterWindow.SashGravity = 1.0;
			splitterWindow.MinimumPaneSize = 50;
			splitterWindow.SplitHorizontally(topWindow, bottomWindow);
		}

		private void DoLayout()
		{
			topSizer = new wx.BoxSizer(wx.Orientation.wxVERTICAL);
			{
				topSizer.Add(splitterWindow, 1, wx.Stretch.wxEXPAND|wx.Direction.wxALL, 5);
			}
			topSizer.Fit(this);
			topSizer.SetSizeHints(this);
			this.Sizer = topSizer;
		}
		
		private void OnRenderMessages(object sender, wx.Event evt)
		{
			messagesMutex.WaitOne();
			{
				topWindow.SetNewPage(messagesHtmlCode);
			}
			messagesMutex.ReleaseMutex();
		}
		
		private void ClearTopWindow(object sender, wx.Event evt)
		{
			messagesHtmlCode = string.Empty;
			OnRenderMessages(sender, evt);
		}
		
		private void OnChatFrameResize(object sender, wx.Event evt)
		{
#if LOG
			logger.Trace(String.Format(Catalog.GetString("Chat frame [{0}] size: {1}x{2}"), chatObject.CallerUin, this.Size.Width, this.Size.Height));
#endif
			evt.Skip();
		}
		
		public void ChatWindowSizeChagned(object sender)
		{
			this.EventHandler.AddPendingEvent(new wx.UpdateUIEvent((int) FakeId.chatWindowSizeChanged));
		}
		
		private void UpdateChatWindowSize(object sender, wx.Event evt)
		{
			this.Size = mainFrame.AppCfg.UserConf.ChatWindowSize;
		}
		
		/// <summary>
		/// Blink chat window icon on taskbar
		/// </summary>
		private void GetUserAttention(object sender, wx.Event evt)
		{
			if (this.Iconized)
				this.RequestUserAttention();
		}
		
		private void OnChatFrameClose(object sender, wx.Event evt)
		{
			mainFrame.Dispatch.CloseChat(chatObject.CallerUin);
			evt.Skip();
		}
		
		//// <value>
		/// Reference to main application window
		/// </value>
		public wx.Frame MainFrame
		{
			get { return mainFrame; }
		}
		
		public TopChatFramePanel TopChatWindow
		{
			get { return topWindow; }
		}
		
		public BottomChatFramePanel BottomWindow
		{
			get { return bottomWindow; }
		}
		
		//// <value>
		/// Html code contains formatted chat messages
		/// </value>
		public string MessagesHtmlCode
		{
			get 
			{ 
				//messagesMutex.WaitOne();
				{
					return messagesHtmlCode; 
				}
				//messagesMutex.ReleaseMutex();
			}
			set 
			{ 
				messagesMutex.WaitOne();
				{
					messagesHtmlCode = value; 
					// render html code into window
					this.EventHandler.AddPendingEvent(new wx.UpdateUIEvent((int) FakeId.chatFrameRenderMessages));
					// blink chat window icon on taskbar
					this.EventHandler.AddPendingEvent(new wx.UpdateUIEvent((int) FakeId.chatFrameRequestUserAttention));
				}
				messagesMutex.ReleaseMutex();
			}
		}
		
		//// <value>
		/// <c>Chat</c> class object connected to 
		/// this chat window
		/// </value>
		public Chat ChatObject
		{
			get { return chatObject; }
		}
	}
}
